﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//    WPFHelpers.cs
//
// Abstract:
//    
//    Helpers methods for Windows Presentation Foundation (WPF) operations.
//
//--

using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.OfficeCommunicationsServer.Applications.Common;

namespace Microsoft.EnhancedReminders.OutlookAddIn
{
    internal static class WPFHelpers
    {
        /// <summary>
        /// Converts a System.Drawing.Bitmap (for Windows Forms) to a BitmapSource usable by WPF.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
        internal static BitmapSource ConvertToBitmapSource(Bitmap bitmap)
        {
            Debug.Assert(bitmap != null, "bitmap");

            return Imaging.CreateBitmapSourceFromHBitmap(
                bitmap.GetHbitmap(),
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
        }

        /// <summary>
        /// Helper method to truncate a string if it exceeds a specified length.
        /// </summary>
        /// <param name="target">The string to test.</param>
        /// <param name="maxLength">The maximum length of the string.</param>
        /// <returns>
        /// The original string if it is less than maxLength charactters; otherwise the
        /// string truncated to maxLength characters and ending in an ellipsis.
        /// </returns>
        internal static string TruncateString(string target, int maxLength)
        {
            // Perform a simple (non-optimal) truncation of the string to maxLength and 
            // replace the last 3 characters with "...".  This requires maxLength to be > 3.
            Debug.Assert(maxLength > 3, "maxLength must be > 3 in order to truncate the condition string correctly");

            if (String.IsNullOrEmpty(target))
            {
                return target;
            }

            return target.Length > maxLength ?
                target.Substring(0, maxLength - 3) + "..." :
                target;
        }
        /// <summary>
        /// Helper method to retrieve the specified item which contains the target in its hierarchy.
        /// </summary>
        /// <typeparam name="T">The type of object containing the target object.</typeparam>
        /// <param name="obj">The target object.</param>
        /// <returns>
        /// The container (of type T) which was found for obj or null if the container was not found.
        /// </returns>
        internal static T GetAncestorItemFromObject<T>(object obj) where T : DependencyObject
        {
            return GetAncestorItemFromObject<T>(obj, /*excludeFromPath*/null, /*suppressAssertion*/false);
        }

        /// <summary>
        /// Helper method to retrieve the specified item which contains the target in its hierarchy.
        /// </summary>
        /// <typeparam name="T">The type of object containing the target object.</typeparam>
        /// <param name="obj">The target object.</param>
        /// <param name="excludeFromPath">Return null if an instance of this item occurs in the search path.</param>
        /// <param name="suppressAssertion">Optionally suppress the assertion if item is not found.</param>
        /// <returns>
        /// The container (of type T) which was found for obj; or null if the container was not found or an 
        /// instance of "excludeFromPath" was found.
        /// </returns>
        /// <remarks>
        /// Parameter "excludeFromPath" is useful when ignoring items from a double-click event such as a 
        /// CheckBox when searching for a target type such as a ListItem in a ListView.
        /// </remarks>
        internal static T GetAncestorItemFromObject<T>(object obj, Type excludeFromPath, bool suppressAssertion) where T : DependencyObject
        {
            Debug.Assert(obj != null, "obj");

            DependencyObject dependencyObject = Helpers.AssertCast<DependencyObject>(obj);
            T item = null;

            while (dependencyObject != null)
            {
                if (dependencyObject.GetType() == excludeFromPath)
                {
                    return null;
                }

                item = dependencyObject as T;
                if (item != null)
                {
                    return item;
                }
                dependencyObject = VisualTreeHelper.GetParent(dependencyObject);
            }

            Debug.Assert(suppressAssertion || item != null, "Could not find item for target object.");

            return null;
        }
    }
}
